package com.example.casper.Experiment2024;


import static android.widget.Toast.LENGTH_LONG;
import static com.example.casper.Experiment2024.TravelRecordsFragment.recordsList;
import android.Manifest;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import androidx.activity.result.ActivityResultLauncher;
import androidx.activity.result.contract.ActivityResultContracts;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AlertDialog;
import androidx.core.app.ActivityCompat;
import androidx.fragment.app.Fragment;
import androidx.lifecycle.viewmodel.CreationExtras;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.Toast;
import com.example.casper.Experiment2024.data.RecordShowActivity;
import com.example.casper.Experiment2024.data.Records;
import com.google.android.material.floatingactionbutton.FloatingActionButton;
import com.tencent.map.lib.thread.AsyncTask;
import com.tencent.tencentmap.mapsdk.maps.CameraUpdateFactory;
import com.tencent.tencentmap.mapsdk.maps.TencentMap;
import com.tencent.tencentmap.mapsdk.maps.TextureMapView;
import com.tencent.tencentmap.mapsdk.maps.model.LatLng;
import com.tencent.tencentmap.mapsdk.maps.model.Marker;
import com.tencent.tencentmap.mapsdk.maps.model.MarkerOptions;
import com.tencent.tencentmap.mapsdk.maps.model.Polyline;
import com.tencent.tencentmap.mapsdk.maps.model.PolylineOptions;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;


public class TravelFootprintsFragment extends Fragment implements LocationListener{
    private TextureMapView TravelmapView;
    private final List<Polyline> polylines=new ArrayList<>();
    private Marker locatemarker;
    private final List<Marker> markers=new ArrayList<>();
    private LocationManager locationManager;
    private TencentMap TravelMap;
    public TravelFootprintsFragment() {}
    private static final long REQUEST_DELAY_MS = 1000; // 每秒一个请求
    private final Queue<String[]> requestQueue = new LinkedList<>();
    private final ExecutorService executor = Executors.newSingleThreadExecutor();
    private static final String SK = "1j4VyyffUc37dzapJV9ktfOF3HaiGuUd"; // 替换为你的SecretKey
    private static final String API_KEY = "QVLBZ-OAFCA-SBBKO-CSXNC-O4NJZ-AOF4B"; // 替换为你的APIKey
    private static final String DIRECTION_URL = "https://apis.map.qq.com/ws/direction/v1/walking/";
    private ActivityResultLauncher<Intent> showItemLauncher;
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        showItemLauncher = registerForActivityResult(
                new ActivityResultContracts.StartActivityForResult(), // 如果RecordShowActivity不需要返回结果，使用StartActivity()
                result -> {
                }
        );
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View rootView = inflater.inflate(R.layout.fragment_travel_footprints, container, false);
        TravelmapView = rootView.findViewById(R.id.mapview_travel);
        TravelMap = TravelmapView.getMap();

        // 添加缩放按钮逻辑
        Button zoomInButton = rootView.findViewById(R.id.zoomInButton);
        Button zoomOutButton = rootView.findViewById(R.id.zoomOutButton);
        Button footPrintButton=rootView.findViewById(R.id.footButton);
        FloatingActionButton locateButton=rootView.findViewById(R.id.floatingActionButton);
        locationManager = (LocationManager) requireActivity().getSystemService(Context.LOCATION_SERVICE);
        if (ActivityCompat.checkSelfPermission(requireContext(), Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED
                && ActivityCompat.checkSelfPermission(requireContext(), Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
            // 请求位置权限
            ActivityCompat.requestPermissions(requireActivity(), new String[]{Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION}, 1);
        }
        locateButton.setOnClickListener(v->locate());
        footPrintButton.setOnClickListener(v->ShowFootPrint());
        zoomInButton.setOnClickListener(v -> TravelMap.animateCamera(CameraUpdateFactory.zoomIn()));
        zoomOutButton.setOnClickListener(v -> TravelMap.animateCamera(CameraUpdateFactory.zoomOut()));
        Button searchButton = rootView.findViewById(R.id.searchButton);
        searchButton.setOnClickListener(v -> {
            // 显示搜索对话框
            Markerremove();
            Polylineremove();
            showSearchDialog();
        });
        TravelMap.setOnMarkerClickListener(marker -> {
            int check = (int) marker.getZIndex();
            if(check<=recordsList.size()&&marker.getTitle().equals(recordsList.get(check).getTitle())) {
                //自定义Marker被点击
                marker.showInfoWindow();
                Toast.makeText(TravelFootprintsFragment.this.getContext(),"Your clicked tencent map", LENGTH_LONG).show();
            }
            return true;
        });
        TravelMap.setOnInfoWindowClickListener(new TencentMap.OnInfoWindowClickListener() {
            @Override
            public void onInfoWindowClick(Marker marker) {
                Log.i("TAG","InfoWindow被点击时回调函数");
                Toast.makeText(TravelFootprintsFragment.this.getContext(),"Your clicked tencent InfoWindow", LENGTH_LONG).show();
                Intent intentShow=new Intent(TravelFootprintsFragment.this.getContext(), RecordShowActivity.class);
                Records recordshow= recordsList.get((int) marker.getZIndex());
                intentShow.putExtra("Title",recordshow.getTitle());
                intentShow.putExtra("photo",recordshow.getPhoto());
                intentShow.putExtra("description",recordshow.getDescription());
                intentShow.putExtra("locationname",recordshow.getLocationname());
                intentShow.putExtra("locationname",recordshow.getLocationname());
                intentShow.putExtra("latitude",recordshow.getLatitude());
                intentShow.putExtra("longitude",recordshow.getLongitude());
                intentShow.putExtra("position",Integer.parseInt(marker.getId())-2);
                showItemLauncher.launch(intentShow);
            }
            @Override
            public void onInfoWindowClickLocation(int width, int height, int x, int y) {
                Log.i("TAG","当InfoWindow点击时，点击点的回调");
            }
        });
        //设置Marker支持点击
        return rootView;
    }

    private void ShowFootPrint() {
        Polylineremove();
        if(!recordsList.isEmpty()&&markers.isEmpty())
        {
            // 设置初始摄像机位置
            LatLng startPoint = new LatLng(
                    recordsList.get(0).getLatitude(),
                    recordsList.get(0).getLongitude()
            );
            Marker marker = TravelMap.addMarker(new MarkerOptions(startPoint).title(recordsList.get(0).getTitle()));
            marker.setClickable(true);
            marker.setZIndex(0);
            markers.add(marker);
            TravelMap.moveCamera(CameraUpdateFactory.newLatLngZoom(startPoint, 13));
            fetchRoutesBetweenAllPoints();
        } else if (!markers.isEmpty())
        {
            Markerremove();
            Polylineremove();
        }
    }

    private void Markerremove() {
        for (Marker marker:markers) {
            marker.remove();
        }
        markers.clear();
    }
    private void Polylineremove()
    {
        for (Polyline p: polylines) {
            p.remove();
        }
        polylines.clear();
    }


    private void locate() {
        if(locatemarker!=null) locatemarker.remove();
        if (ActivityCompat.checkSelfPermission(requireContext(), Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
            locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0,  0, TravelFootprintsFragment.this);
            Location lastKnownLocation = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
            assert lastKnownLocation != null;
            LatLng Point=new LatLng(lastKnownLocation.getLatitude(),lastKnownLocation.getLongitude());
            locatemarker=TravelMap.addMarker(new MarkerOptions(Point));
            TravelMap.moveCamera(CameraUpdateFactory.newLatLngZoom(Point, 19));
        }
    }
    private void showSearchDialog() {
        // 这里可以使用 AlertDialog 或 BottomSheetDialog
        // 以下是一个简单的 AlertDialog 示例
        AlertDialog.Builder builder = new AlertDialog.Builder(requireActivity());
        builder.setTitle("搜索位置");

        // 创建一个 LinearLayout 来包含 EditText 字段
        LinearLayout layout = new LinearLayout(getActivity());
        layout.setOrientation(LinearLayout.VERTICAL);

        EditText latEditText = new EditText(getActivity());
        latEditText.setHint("纬度");
        layout.addView(latEditText);

        EditText lngEditText = new EditText(getActivity());
        lngEditText.setHint("经度");
        layout.addView(lngEditText);

        builder.setView(layout);

        builder.setPositiveButton("搜索", (dialog, which) -> {
            // 获取用户输入的经纬度
            String lat = latEditText.getText().toString();
            String lng = lngEditText.getText().toString();
            // 执行搜索逻辑
            performSearch(lat, lng);
        });

        builder.setNegativeButton("取消", (dialog, which) -> {
            // 用户取消了搜索
        });
        builder.show();
    }
    // 执行搜索逻辑的方法（需要您自己实现）‌经度：113.5413
    //‌纬度：22.2345
    public void performSearch(String lat, String lng) {
        polylines.clear();
        requestQueue.clear();
        if (ActivityCompat.checkSelfPermission(requireContext(), Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
            locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0,  0, TravelFootprintsFragment.this);
            Location lastKnownLocation = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
            assert lastKnownLocation != null;
            synchronized (requestQueue) {
                requestQueue.add(new String[]{
                        String.valueOf(lastKnownLocation.getLatitude()),
                        String.valueOf(lastKnownLocation.getLongitude()), lat, lng
                });
            }
        }
        executor.execute(() -> {
            try {
                while (!requestQueue.isEmpty()) {
                    String[] request = requestQueue.poll();
                    assert request != null;
                    new FetchRouteTask().execute(request[0], request[1], request[2], request[3]);
                    TimeUnit.MILLISECONDS.sleep(REQUEST_DELAY_MS);//采用请求队列处理并发问题
                }
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
                Log.e("RouteFetcher", "Thread was interrupted", e);
            }
        });
    }
    public void fetchRoutesBetweenAllPoints() {
        if (recordsList == null || recordsList.isEmpty()) {
            return;
        }
        // 清空之前的请求队列，避免重复处理
        requestQueue.clear();
        for (int i = 0; i < recordsList.size() - 1; i++) {
            Records currentRecord = recordsList.get(i);
            Records nextRecord = recordsList.get(i + 1);
            LatLng currentPoint = new LatLng(currentRecord.getLatitude(), currentRecord.getLongitude());
            LatLng nextPoint = new LatLng(nextRecord.getLatitude(), nextRecord.getLongitude());
            // 添加标记到地图（这部分逻辑可能需要根据实际需求调整）
            Marker marker = TravelMap.addMarker(new MarkerOptions(nextPoint).title(nextRecord.getTitle()));
            marker.setZIndex(i+1);
            marker.setClickable(true);
            markers.add(marker);
            // 将请求添加到队列中
            synchronized (requestQueue) {
                requestQueue.add(new String[]{
                        String.valueOf(currentPoint.latitude),
                        String.valueOf(currentPoint.longitude),
                        String.valueOf(nextPoint.latitude),
                        String.valueOf(nextPoint.longitude)
                });
            }
        }
        // 开始处理请求队列
        executor.execute(() -> {
            try {
                while (!requestQueue.isEmpty()) {
                    String[] request = requestQueue.poll();
                    assert request != null;
                    new FetchRouteTask().execute(request[0], request[1], request[2], request[3]);
                    TimeUnit.MILLISECONDS.sleep(REQUEST_DELAY_MS);//采用请求队列处理并发问题
                }
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
                Log.e("RouteFetcher", "Thread was interrupted", e);
            }
        });
    }

    @Override
    public void onLocationChanged(@NonNull Location location) {}

    @Override
    public void onLocationChanged(@NonNull List<Location> locations) {
        LocationListener.super.onLocationChanged(locations);
    }

    @Override
    public void onFlushComplete(int requestCode) {
        LocationListener.super.onFlushComplete(requestCode);
    }

    @Override
    public void onStatusChanged(String provider, int status, Bundle extras) {
        LocationListener.super.onStatusChanged(provider, status, extras);
    }

    @Override
    public void onProviderEnabled(@NonNull String provider) {
        LocationListener.super.onProviderEnabled(provider);
    }

    @Override
    public void onProviderDisabled(@NonNull String provider) {
        LocationListener.super.onProviderDisabled(provider);
    }

    @NonNull
    @Override
    public CreationExtras getDefaultViewModelCreationExtras() {
        return super.getDefaultViewModelCreationExtras();
    }

    // 异步任务获取路线信息
    private class FetchRouteTask extends AsyncTask<String, Void, String> {
        public FetchRouteTask() {
        }
        @Override
        protected String doInBackground(String... params) {
            String originLat = params[0];
            String originLng = params[1];
            String destinationLat = params[2];
            String destinationLng = params[3];
            try {
                String sig = generateSignature(originLat, originLng, destinationLat, destinationLng);
                String url = DIRECTION_URL + "?from=" + originLat + "," + originLng +
                        "&to=" + destinationLat + "," + destinationLng +
                        "&key=" + API_KEY + "&sig=" + sig;

                HttpURLConnection connection = (HttpURLConnection) new URL(url).openConnection();
                connection.setRequestMethod("GET");
                BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream()));
                StringBuilder response = new StringBuilder();
                String inputLine;
                while ((inputLine = in.readLine()) != null) {
                    response.append(inputLine);
                }
                in.close();
                return response.toString();
            } catch (Exception e) {
                Log.e("FetchRouteTask", "Failed to fetch route", e);
                return null;
            }
        }
        @Override
        protected void onPostExecute(String result) {
            super.onPostExecute(result);
            if (result != null) {
                try {
                    JSONObject json = new JSONObject(result);
                    JSONObject resultObj = json.getJSONObject("result");
                    JSONArray routes = resultObj.getJSONArray("routes");
                    if (routes.length() > 0) {
                        JSONObject route = routes.getJSONObject(0);
                        JSONArray polyline = route.getJSONArray("polyline");
                        List<LatLng> points = decodePolyline(polyline);
                        polylines.add(TravelMap.addPolyline(new PolylineOptions().addAll(points)
                                .color(0x88FF0000).width(20)));
                    } else {
                        Log.w("FetchRouteTask", "No routes found in response");
                    }
                } catch (Exception e) {
                    Log.e("FetchRouteTask", "Failed to process route response", e);
                }
            }
        }
    }

    private List<LatLng> decodePolyline(JSONArray polyline) throws JSONException {
        // 校验 polyline 数据有效性
        if (polyline == null || polyline.length() < 2) {
            throw new JSONException("Invalid polyline data: Must have at least two entries for latitude and longitude.");
        }
        List<Double> coors = new ArrayList<>();
        for (int i = 0; i < polyline.length(); i++) {
            coors.add(polyline.getDouble(i));
        }
        // 调用提供的解压函数
        List<Double> decoded = decodePolyline(coors);
        // 转换解压后的结果为 LatLng 列表
        List<LatLng> points = new ArrayList<>();
        for (int i = 0; i < decoded.size(); i += 2) {
            points.add(new LatLng(decoded.get(i), decoded.get(i + 1)));
        }
        return points;
    }
    // 提供的 polyline 解压逻辑函数
    public static List<Double> decodePolyline(List<Double> coors) {
        // 校验输入数据有效性
        if (coors == null || coors.size() < 2) {
            throw new IllegalArgumentException("Polyline data must contain at least two values for latitude and longitude.");
        }
        // 解压逻辑
        List<Double> decoded = new ArrayList<>(coors); // 创建解压结果列表，初始化为原始数据
        for (int i = 2; i < decoded.size(); i++) {
            decoded.set(i, decoded.get(i - 2) + decoded.get(i) / 1000000.0); // 按前向差分解压
        }
        return decoded;
    }
    private String generateSignature(String originLat, String originLng, String destinationLat, String destinationLng) throws NoSuchAlgorithmException {
        String originalString = "/ws/direction/v1/walking/?from=" + originLat + "," + originLng +
                "&key=" + API_KEY + "&to=" + destinationLat + "," + destinationLng + SK;
        MessageDigest md = MessageDigest.getInstance("MD5");
        byte[] digest = md.digest(originalString.getBytes());
        StringBuilder sb = new StringBuilder();
        for (byte b : digest) {
            sb.append(String.format("%02x", b));
        }
        return sb.toString();
    }
    @Override
    public void onStart() {
        super.onStart();
        TravelmapView.onStart();
    }
    @Override
    public void onResume() {
        super.onResume();
        TravelmapView.onResume();
    }
    @Override
    public void onStop() {
        super.onStop();
        TravelmapView.onStop();
    }
    @Override
    public void onPause() {
        super.onPause();
        TravelmapView.onPause();
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        TravelmapView.onDestroy();
    }
}